﻿using System;
using System.Collections.Generic;

namespace ManagedServices.Common.Utility
{
    /// <summary>
    /// This is a basic Service Locator Implemenatation for Getting to Services from a Single point
    /// </summary>
    public class ServiceLocator
    {
        /// <summary>
        /// Self Instance for Singleton Implementation
        /// </summary>
        private static ServiceLocator _selfInstance;

        /// <summary>
        /// Locl object for Thread Safety
        /// </summary>
        private static readonly object _lock = new object();

        /// <summary>
        /// The internal storage of the Service Locator
        /// </summary>
        private readonly Dictionary<Type, object> _internalServiceStore;

        /// <summary>
        /// protected Constructor of the Service Locator Class
        /// </summary>
        private ServiceLocator()
        {
            _internalServiceStore = new Dictionary<Type, object>();
        }

        /// <summary>
        /// Method to provide Instance of the Service Locator Class
        /// </summary>
        public static ServiceLocator Instance
        {
            get
            {
                if (_selfInstance == null)
                {
                    lock (_lock)
                    {
                        if (_selfInstance == null)
                        {
                            _selfInstance = new ServiceLocator();
                        }
                    }
                }
                return _selfInstance;
            }
        }

        /// <summary>
        /// Registers the Service to the Service Locator
        /// </summary>
        /// <typeparam name="TTypeOfService"></typeparam>
        /// <param name="service"></param>
        public void RegisterService<TTypeOfService>(TTypeOfService service) where TTypeOfService : class
        {
            _internalServiceStore.Add(typeof (TTypeOfService), service);
        }

        /// <summary>
        /// Gets the Service from the Service Locator on basis of the Type of the Service
        /// </summary>
        /// <typeparam name="TTypeOfService"></typeparam>
        /// <returns></returns>
        public TTypeOfService GetService<TTypeOfService>() where TTypeOfService : class
        {
            return (TTypeOfService) _internalServiceStore[typeof (TTypeOfService)];
        }
    }
}